package main

import (
      //  "http"
       // "io"
      //  "flag"
      //  "os"
       "fmt"
       // "strings"
	"time"
//	"netchan"
	"sync"
)

type log_data struct {
	id int64
	key string
	value string
	time_written int64
}

type write_log struct {
	log []log_data;
	write_pointer int;
	log_start int;
}

var wlogs []write_log;
var logMutex []sync.Mutex
var num_logs int;

func initLog(n int) {
	wlogs = make([]write_log,n+1,1000);
	num_logs=n;
	for i:=1; i<n+1; i++ {
		wlogs[i].log = make([]log_data,500,1000)
		wlogs[i].write_pointer=0;
		wlogs[i].log_start=0;
	}
	logMutex = make([]sync.Mutex, n+2, 1000)
	//fmt.Println("Logs initiazed for ",n," partitions")
}

func printLog(n int) {
	for i:=wlogs[n].log_start; i< wlogs[n].write_pointer; i++ {
		fmt.Println(wlogs[n].log[i].id,wlogs[n].log[i].key, wlogs[n].log[i].value, wlogs[n].log[i].time_written);		
	}
}

func printAllLogs() {
	for i:=1; i< num_logs+1; i++ {
		fmt.Println("Contents of log for partition ",i);
		printLog(i);
	}
}

func log_append(partitionNumber int, key string, value string) {

	logMutex[partitionNumber].Lock()
	
	wp := wlogs[partitionNumber].write_pointer
	//fmt.Println("Inside log_append:wp,pN",wp,partitionNumber)

	len_log := len(wlogs[partitionNumber].log)

	if wp >= len_log {
		//fmt.Println("Need to grow");

		if len_log+100 > cap(wlogs[partitionNumber].log) {
			//fmt.Println("Need to change capacity")
			newlog := make([]log_data, len_log + 1000 + (wp-len_log), len_log + 2000 + (wp-len_log) )

			for i, c := range wlogs[partitionNumber].log {
            			newlog[i] = c
        		}
			wlogs[partitionNumber].log = newlog
		}

		wlogs[partitionNumber].log = wlogs[partitionNumber].log[0:len_log+(wp-len_log)+50]
	} //else {

	wlogs[partitionNumber].log[wp].key = key;
	wlogs[partitionNumber].log[wp].value = value;
	wlogs[partitionNumber].log[wp].id =  int64(wp);
	wlogs[partitionNumber].log[wp].time_written = time.Nanoseconds()
	
	wlogs[partitionNumber].write_pointer++

	logMutex[partitionNumber].Unlock()
	//}
}

func printReqLog(partitionNumber int,start_point int) {
	req_log := wlogs[partitionNumber].log[start_point:wlogs[partitionNumber].write_pointer]

	fmt.Println("Required data is: \n");

	for i,c := range req_log {
		fmt.Println(c.id, c.key, c.value,c.time_written)
		fmt.Println(i);
	}
	
	fmt.Println("End of required data\n");
}
